//@author A0101056Y
//SearchEngine class faciliate the operation search
//It checks an event according to the search information entered
//by users. It is able to check against event's descriptions, 
//time (deadline or duration), tags and filters like isDone,
//isReminded, repeatable, favourite and missed. To use it, 
//	SearchEngine engine; 
//	engine.setEverything(event, searchInfo, eventIndex);
//	engine.foundEvents();


#pragma once

#include <algorithm>
#include <cmath>
#include <vector>
#include "Event.h"
#include "CommonDataType.h"
#include "ThrowErrorCode.h"

using std::abs;
using std::vector;
using namespace SearchConstants;
using namespace StringManipulator;

//@author A0083782W
class MyTime:public Time {
public:
	Month gotoNextMonth ();
	void operator = (const Time& rightOperand);
	bool operator == (const MyTime& rightOperand); 
	MyTime (const Time& theOtherTime);

};

//@author A0101056Y
class SearchEngine {
private:
	Event _myEvent;
	SEARCH_STRUCT _mySearchInfo; 
	pos_int _myEventIndex; 
	vector<SEARCH_RELEVANCE> _foundEvents;

public:
	
	void setEverything(
		const Event &anEvent, 
		const SEARCH_STRUCT &searchInfo, 
		const pos_int &eventIndex); 

	vector<SEARCH_RELEVANCE> getFoundEvents();
	void searchEvents();
	void checkDetailsMet (pos_int &match, pos_int &distance);
	void checkTagMet (pos_int &match, pos_int &distance);
	void checkTimeMet (pos_int &match, pos_int &distance);
	bool isFiltersMet();
	void setFoundEvents (
		vector<SEARCH_RELEVANCE> &foundEvents, 
		pos_int index, 
		pos_int &match, 
		pos_int &distance);
};

template <typename T> static void foundMatch (
	vector<T> &keywords, 
	vector<T> &targets, 
	pos_int &count, 
	pos_int &distance){

	int lastPos = -1;
	for (int i = 0; i< (int)keywords.size(); i++) {
		for (int j = 0; j< (int)targets.size(); j++ ){
			if (keywords[i] == targets[j]) {
				(count) ++;
				if (lastPos >= 0) {
					(distance) += abs(j - lastPos) - 1;
				}
				lastPos = j;
				break;
			}
		}
	}
};

static bool compareByRelevance (const SEARCH_RELEVANCE &a, const SEARCH_RELEVANCE &b){
	return a.relevanceIndex > b.relevanceIndex ; 
}